<?php
/**
 * Created by PhpStorm.
 * User: guokunsheng
 * Date: 2018/12/14
 * Time: 22:27
 */

namespace app\common\lib;

use app\common\cachemodel\AppConfig;
use app\common\cachemodel\AwardUser as AwardUserModel;
use app\common\cachemodel\FortuneRecodeBack;
use app\common\cachemodel\Orders as OrdersCacheModel;
use app\common\lib\astrolog\FortunesChange;
use app\common\model\AppLogicVersion;
use app\common\model\MessageCenter;
use app\common\model\MonthFortune;
use app\common\model\Orders;
use app\common\model\SystemLogicVersion;
use app\common\model\User;
use app\common\model\YearFortune;
use think\Exception;
use think\Log;
use think\queue\job;
use think\Cache;
use XznsTools\cache\CacheManage;

/**
 * 月运年运消费队列
 * Class FortuneJob
 * @package app\common\lib
 */
class FortuneJob
{
    /**
     * 运势计算队列
     * @param job $job
     * @param $jobData
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function task1(Job $job, $jobData)
    {
        // 可以根据业务需求和数据库中的最新数据,判断该任务是否仍有必要执行.
        $jobAttempts = $job->attempts();
        if ($jobAttempts > 1)
        {
            $job->delete();
        }

        $host = Util::getEcsIp();

        if ($jobData['type'] === 'year')
        {
            $logInfo = '年运';
        } else
        {
            $logInfo = '月运';
        }
        $startTime = date('Y-m-d H:i:s');
        $logInfo .= $jobData['start_time'][0] . "计算 开始:{$startTime} host:{$host} uid:{$jobData['recode'][0]['uid']} rid:{$jobData['recode'][0]['id']} name:{$jobData['recode'][0]['name']}";

        try
        {
            // 计算数据，并入库、写入缓存
            $res = $this->fireData($jobData);

            // 更新订单状态为，计算完成
            if (isset($jobData['oid'], $jobData['status']) && $jobData['oid'] && $res === true)
            {
                $OrdersModel = new Orders();
                try
                {
                    //更新2.0订单缓存
                    (new OrdersCacheModel())->UpdateData($jobData['order_id'], ['status' => 4], 4);
                    //删除订单详情
                    Cache::rm(Orders::ORDER_INFO_ID . $jobData['oid']);
                    Cache::rm(Orders::ORDER_INFO_ID . $jobData['order_id']);
                    // 删除订单缓存
                    $OrdersModel->rm_cache(['oid' => $jobData['oid'], 'del_add' => 0, 'uid' => $jobData['recode'][0]['uid']]);

                    $db_update_status = true;
                }
                catch (\Exception $e)
                {
                    $db_update_status = false;
                    //更新订单状态失败
                    $logInfo .= ' error:' . $e->getMessage() . ' file:' . $e->getFile() . ':' . $e->getLine();
                }
            } elseif (isset($jobData['aid']) && $jobData['aid'] && $res === true)
            {
                // 后台赠送时,修改状态
                try
                {
                    (new AwardUserModel())->UpdateData($jobData['recode'][0]['uid'], $jobData['aid'], $jobData['ftype'], ['status' => 1]);

                    if (in_array($jobData['ftype'], [2, 3]))
                    {
                        $jobData['ftype'] = $jobData['ftype'] + 1;
                    }
                    Cache::rm($jobData['recode'][0]['uid'] . '_' . $jobData['recode'][0]['id'] . '_award_fortune_' . $jobData['ftype']);

                    $db_update_status = true;
                }
                catch (\Exception $e)
                {
                    $db_update_status = false;
                    //更新订单状态失败
                    $logInfo .= ' error:' . $e->getMessage() . ' file:' . $e->getFile() . ':' . $e->getLine();
                }
            } else
            {
                $db_update_status = false;
                $logInfo .= ' error:队列异常';
            }

            if ($db_update_status === true)
            {
                //获取用户信息
                $userinfo = (new User())->getUserinfo(['id' => $jobData['recode'][0]['uid']]);

                //若开启推送开关则发送推送和消息
                if (isset($jobData['push_switch']) && $jobData['push_switch'])
                {
                    // PUSH推送
                    $pushRes = (new Push())->pushUserMsg($userinfo['id'],
                        '您购买的' . $jobData['recode'][0]['name'] . '的运势' . $jobData['start_time'][0] . '已经计算完成了，点击查看运势详情！',
                        ['action' => 'fortune_for_' . $jobData['type'], 'rid' => $jobData['recode'][0]['id'], 'time' => $jobData['start_time'][0]]);

                    if (!$pushRes['success'])
                    {
                        // 运势计算完成推送失败
                        $logInfo .= ' error: 计算完成,推送失败 message:' . $pushRes['message'];
                    }

                    // 短信通知
                    if ($userinfo && $userinfo['tel'] != '' && config('queue.fortune_sendsms') == 1)
                    {
                        try
                        {
                            $recode_names = '「';
                            foreach ($jobData['recode'] as $re) $recode_names .= $re['name'] . '、';
                            $recode_names = rtrim($recode_names, '、');
                            $recode_names .= '」';

                            $fortune_times = $jobData['start_time'][0];

                            if (count($jobData['start_time']) > 1)
                            {
                                $fortune_times .= '至' . end($jobData['start_time']);
                            }

                            $sms_param = $recode_names . '的' . $fortune_times . '运势';

                            $alidayu = (new AppConfig())->configInfo('alidayu');
                            $sendSmsResult = sendSms($userinfo['tel'], ['orderId' => $sms_param], $alidayu['fortune_code']);

                            if (!empty($sendSmsResult) && $sendSmsResult['Code'] !== 'OK')
                            {
                                // 运势计算完成短信通知失败
                                $logInfo .= ' error: 计算完成,短信通知失败 message:' . $sendSmsResult['Message'];
                            }
                        }
                        catch (\Exception $e)
                        {
                            // 运势计算完成短信通知失败
                            $logInfo .= ' error:' . $e->getMessage() . ' file:' . $e->getFile() . ':' . $e->getLine();
                        }
                    }
                    // 消息中心添加信息
                    $messageData = [
                        'status' => 0,
                        'is_read' => 0,
                        'range' => $userinfo['id'],
                        'type' => 2,
                        'reid' => 0,
                        'cid' => 3,// 年运月运
                        'title' => '运势计算完成',
                        'content' => '您购买的' . $jobData['recode'][0]['name'] . '的运势' . $jobData['start_time'][0] . '已经计算完成了，点击查看运势详情！',
                        'link' => 'fortune_for_' . $jobData['type'] . '?rid=' . $jobData['recode'][0]['id'] . '&time=' . $jobData['start_time'][0] . '&need_auth=1',
                        'target' => 'local',
                        'create_time' => time()
                    ];
                    //添加消息
                    (new MessageCenter())->pushMessage($userinfo['id'], $messageData);
                }
                $logInfo .= ' success:' . date('Y-m-d H:i:s');

                $job->delete();
            } else
            {
                $job->delete();
                $logInfo .= ' failed:' . date('Y-m-d H:i:s');
            }
        }
        catch (Exception $e)
        {
            $logInfo .= ' error:' . $e->getMessage() . ' file:' . $e->getFile() . ':' . $e->getLine();
        }

        $logInfo .= ' jobData:' . json_encode($jobData, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        print(date('Y-m-d H:i:s') . ' ' . $logInfo);
        Log::write($logInfo, 'log', true);
    }

    /**
     * @param $jobData
     * @return bool
     * @throws exception\ApiException
     */
    private function fireData($jobData)
    {
        $monthFortune = new MonthFortune();

        $isYear = $jobData['type'] === 'year';
        $fortuneUnlockType = (isset($jobData['oid'], $jobData['status']) && $jobData['oid']) ? 1 : 2; //运势解锁类型 1=> 下单购买 2=>系统赠送
        if (is_array($jobData['start_time']) && !empty($jobData['start_time']) && is_array($jobData['recode']) && !empty($jobData['recode']))
        {
            $res = true;
            // 多档案
            foreach ($jobData['recode'] as $recode)
            {
                $recodeData = [
                    'id' => $recode['id'],
                    'name' => $recode['name'],
                    'type' => $recode['type'],
                    'year' => $recode['year'],
                    'month' => $recode['month'],
                    'day' => $recode['day'],
                    'hour' => $recode['hour'],
                    'minute' => $recode['minute'],
                    'timezone' => $recode['timezone'],
                    'birth_country' => $recode['birth_country'],
                    'birth_province' => $recode['birth_province'],
                    'birth_city' => $recode['birth_city'],
                    'live_country' => $recode['live_country'],
                    'live_province' => $recode['live_province'],
                    'live_city' => $recode['live_city'],
                    'long_deg' => $recode['long_deg'],
                    'long_min' => $recode['long_min'],
                    'ew' => $recode['ew'],
                    'lat_deg' => $recode['lat_deg'],
                    'lat_min' => $recode['lat_min'],
                    'ns' => $recode['ns'],
                    'avatar' => $recode['avatar'],
                    'is_summer' => $recode['is_summer'],
                    'uid' => $recode['uid'],
                ];
                $backRid = (new FortuneRecodeBack())->insertGetId(['recode_info' => \GuzzleHttp\json_encode($recodeData, JSON_UNESCAPED_UNICODE)]);
                // 多运势时间
                foreach ($jobData['start_time'] as $st_time)
                {
                    // 年运计算
                    if ($isYear)
                    {
                        $data = [
                            'topics' => [],
                            'scores' => [],
                            'topic' => null,
                            'point' => null,

                        ];
                        $insertDataMonth = [];
                        $map = [
                            'rid' => $recode['id'],
                            'month' => [],
                        ];
                        for ($i = 1; $i < 13; $i++)
                        {
                            // 年-月 char(7)
                            $start_time = $st_time . '-' . str_pad($i, 2, '0', STR_PAD_LEFT);

                            $temp = $this->fireDataBase([
                                'recode' => $recode,
                                'start_time' => $start_time,
                                'type' => $jobData['type'],
                            ]);

                            $data['topics'] = array_merge($data['topics'], $temp['topics']);
                            $data['scores'] += $temp['scores'];
                            if ($data['topic'] === null) $data['topic'] = $temp['topic'];
                            if ($data['point'] === null) $data['point'] = $temp['point'];

                            // Cache::set('fortune_month_' . $recode['id'] . '_' . $start_time, json_encode($temp['topics']), 86400 * 7);
                            CacheManage::getInstance()->setCacheConfig('fortune.fortune_month', $recode['id'] . ':' . $start_time)
                                ->setCache(json_encode($temp['topics']), 'details', false);

                            $insertDataMonth[] = [
                                'type' => 0,
                                'order_id' => 0,
                                'rid_back' => $backRid,
                                'status' => 0,
                                'rid' => $recode['id'],
                                'month' => $start_time,
                                'fortune' => json_encode($temp['topics']),
                            ];
                            $map['month'][] = $start_time;
                        }

                        $map['month'] = ['in', $map['month']];

                        $monthFortune->addFortuneForYear($insertDataMonth, $map);

                        $yearCacheTemp = [
                            'scores' => json_encode($data['scores']),
                            'topic' => $data['topic'],
                            'point' => json_encode($data['point']),
                        ];
                        //Cache::set('fortune_year_' . $recode['id'] . '_' . $st_time, $yearCacheTemp, 86400 * 7);
                        CacheManage::getInstance()->setCacheConfig('fortune.fortune_year', $recode['id'] . ':' . $st_time)
                            ->setCache($yearCacheTemp, 'details', false);

                        $yearFortune = new YearFortune();

                        $insertDataYear = [
                            'order_id' => $fortuneUnlockType === 1 ? $jobData['order_id'] : $jobData['aid'],
                            'rid_back' => $backRid,
                            'rid' => $recode['id'],
                            'year' => $st_time,
                            'fortune' => json_encode($data['scores']),
                            'topic' => $data['topic'],
                            'point' => json_encode($data['point']),
                            'type' => $fortuneUnlockType,
                            'status' => 2
                        ];

                        $yearFortune->addFortune($insertDataYear);

                        $logicVersionData = [
                            'rid' => $recode['id'],
                            'type' => 3,
                        ];

                    } // 月运计算
                    else
                    {
                        if (strlen($st_time) == 6)
                        {
                            $st_time = str_replace('-', '-0', $st_time);
                        }
                        $fireData = [
                            'recode' => $recode,
                            'start_time' => $st_time,
                            'type' => $jobData['type'],
                        ];
                        $data = json_encode($this->fireDataBase($fireData), true);
                        // 写入缓存
                        // Cache::set('fortune_month_' . $recode['id'] . '_' . $st_time, $data, 86400 * 7);
                        CacheManage::getInstance()->setCacheConfig('fortune.fortune_month', $recode['id'] . ':' . $st_time)
                            ->setCache($data, 'details', false);

                        $insertData = [
                            'type' => $fortuneUnlockType,
                            'order_id' => $fortuneUnlockType === 1 ? $jobData['order_id'] : $jobData['aid'],
                            'rid_back' => $backRid,
                            'rid' => $recode['id'],
                            'month' => $st_time,
                            'fortune' => $data,
                            'status' => 2,
                        ];
                        $monthFortune->addFortune($insertData);

                        $logicVersionData = [
                            'rid' => $recode['id'],
                            'type' => 2,
                        ];
                    }
                    // 获取当前最新的逻辑版本号
                    $SystemLogicModel = new SystemLogicVersion();
                    $logic_lastes = $SystemLogicModel->getVersion(['type' => $logicVersionData['type']]);

                    $logicVersionData['version'] = $logic_lastes['version'] ?? 0;
                    $logicVersionData['time'] = $st_time;

                    //获取当前档案逻辑版本号
                    $AppLogicModel = new AppLogicVersion();
                    $logic_user = $AppLogicModel->getVersion([
                        'rid' => $recode['id'],
                        'type' => $logicVersionData['type'],
                        'time' => $logicVersionData['time'],
                    ]);
                    // 新增
                    if (!$logic_user)
                    {
                        $AppLogicModel->addVersion($logicVersionData);
                    } // 更新了逻辑
                    elseif ($logicVersionData['version'] && $logic_user <= $logicVersionData['version'])
                    {
                        $AppLogicModel->updateVersion($logicVersionData);
                    }
                }
            }
        } else
        {
            $res = false;
            print('任务数据参数错误' . PHP_EOL);
            Log::write('任务数据参数错误:' . var_export($jobData, true), 'error', true);
        }

        return $res;
    }

    /**
     * 只负责重新生成数据
     * @param $jobData
     * @return array|bool|mixed
     * @throws exception\ApiException
     */
    private function fireDataBase($jobData)
    {
        $isYear = $jobData['type'] == 'year';

        $data = (new FortunesChange())->jobInit($jobData['recode'], $jobData['start_time'], $jobData['type']);

        if ($isYear)
        {
            return $data;
        }
        return $data['topics'];
    }

    public function failed($data)
    {
        // 任务失败了
        print('任务失败数据：' . var_export($data, true) . PHP_EOL);
        \think\Log::write('任务失败：' . var_export($data, true), 'error', true);

        // 重新发布任务
    }
}
